import pickle
from PySide6.QtCore import Signal, QObject
from PySide6.QtNetwork import QTcpSocket, QAbstractSocket

class TcpClient(QObject):
    Connected = Signal(str, int)
    DisConnected = Signal()
    DateReceived = Signal(str)

    def __init__(self):
        super().__init__()

        self.__peerIp = ""
        self.__peerPort = 0
        self.__TcpSocket = QTcpSocket()

        self.__TcpSocket.connected.connect(self.on_connected)
        self.__TcpSocket.disconnected.connect(self.on_disconnected)

        self.__TcpSocket.readyRead.connect(self.on_readMessage)
        self.__TcpSocket.errorOccurred.connect(self.on_displayError)

    def __del__(self):
        self.DisConnect()
        if (self.__TcpSocket is not None):
            self.__TcpSocket.close()
            del self.__TcpSocket
            self.__TcpSocket = None

    def GetIP(self):
        return self.__peerIp

    def GetPort(self):
        return self.__peerPort

    def Connect(self, ip, port):
        if port <= 0:
            return
        
        if self.__peerIp == ip and self.__peerPort == port:
            return

        if self.__TcpSocket.state() != QAbstractSocket.UnconnectedState:
            self.__TcpSocket.disconnectFromHost()

        self.__TcpSocket.connectToHost(ip, port)
        self.__peerIp = ip
        self.__peerPort = port

    def DisConnect(self):
        self.__peerIp = ""
        self.__peerPort = 0
        self.__TcpSocket.disconnectFromHost()

    def SendData(self, json):
        if self.__TcpSocket.state() == QAbstractSocket.ConnectedState:
            return (self.__TcpSocket.write(pickle.dumps(json)) > 0)
        else:
            return False

    def on_connected(self):
        self.Connected.emit(self.__peerIp, self.__peerPort)

    def on_disconnected(self):
        self.__peerIp = ""
        self.__peerPort = 0

        self.DisConnected.emit()

    def on_readMessage(self):
        msg = ""
        while self.__TcpSocket.bytesAvailable():
            # 一次性读取缓存中所有数据
            msg += self.__TcpSocket.readAll()
        #print(msg)
        self.DateReceived.emit(msg)

    def on_displayError(self, socketError):
        #远程服务端关闭连接错误
        if socketError == QAbstractSocket.RemoteHostClosedError:
            self.__TcpSocket.disconnectFromHost()
            print("server close now")
        else:
            print("error id: " + self.__TcpSocket.error().name)
            print("error message: " + self.__TcpSocket.errorString())

